package tmt.usercenter.web.controller;


import com.tmt.helper.RandomCodeHelper;
import com.tmt.sm.impl.ReturnMode;
import com.tmt.spring.validation.RegisterValidateHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import tmt.usercenter.web.configure.emailservice.IEmailSender;
import tmt.usercenter.web.domain.ClientSystem;
import tmt.usercenter.web.domain.TmtUser;
import tmt.usercenter.web.domain.enums.FuncPointType;
import tmt.usercenter.web.domain.enums.SystemParamCode;
import tmt.usercenter.web.service.*;
import tmt.usercenter.web.vo.HttpResult;
import tmt.usercenter.web.vo.user.RegisterVo;

import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.text.MessageFormat;

import static org.springframework.security.web.WebAttributes.AUTHENTICATION_EXCEPTION;

@Controller
@RequestMapping("/")
public class LoginController extends BaseController {

    @Autowired
    private ClientSystemService clientSystemService;

    @Autowired
    private TmtUserService userService;

    @Autowired
    private SystemParamService systemParamService;

    @Autowired
    private SmHistoryService smHistoryService;

    @Autowired
    private IEmailSender emailSender;


    @RequestMapping(value = "/login/index")
    public String topLogin() {
        return "redirect_login";
    }

    @RequestMapping(value = "/login")
    public String displayLoginPage(HttpServletRequest request, Model model,
                                   Principal principal) {
        try {
            String clientId = getClientId(request);
            ClientSystem clientSystem = clientSystemService.findByClientId(clientId);
            if (clientSystem != null) {
                model.addAttribute("clientId", clientId);
                model.addAttribute("clientLogo", clientSystem.getLogo());
                model.addAttribute("clientName", clientSystem.getName());
            }

            String error = request.getParameter("error");
            if (error != null) {
                Object ex = request.getSession().getAttribute(AUTHENTICATION_EXCEPTION);
                if (ex != null) {
                    Exception exception = (Exception) ex;
                    if ("user.login.blocked".equals(exception.getMessage())) {
                        Object obj = request.getSession().getAttribute(LoginAttemptService.MINUTES_FOR_ALLOWED_LOGIN_ATTEMPT_COUNT);
                        model.addAttribute("errorMsg", messageSourceAccessor.getMessage("user.login.blocked", new Object[]{obj}));
                    } else {
                        Object obj = request.getSession().getAttribute(LoginAttemptService.ALLOWED_LOGIN_ATTEMPT_COUNT);
                        model.addAttribute("errorMsg", messageSourceAccessor.getMessage("user.login.usernameNotFound", new Object[]{obj}));
                    }
                } else {
                    model.addAttribute("errorMsg", "");
                }
            }
        } catch (Exception ex) {
        }

        return "login";
    }

    @RequestMapping(value = "/forgot", method = RequestMethod.GET)
    public String forgot(Model model, HttpServletRequest request) {
        boolean mobileMode = isMobileMode();
        model.addAttribute("mobileMode", mobileMode);
        model.addAttribute("user", new RegisterVo());
        return "user/forgot";
    }

    @RequestMapping(value = "/forgot", method = RequestMethod.POST)
    public String forgot(@ModelAttribute("user") RegisterVo registerVo, BindingResult result,
                         Model model, HttpServletRequest request, RedirectAttributes attr) {

        boolean mobileMode = isMobileMode();

        TmtUser user = null;
        if (StringUtils.isEmpty(registerVo.getUsername())) {
            result.rejectValue("username", null, "用户账号不能为空");
        } else {
            user = userService.findByUsername(registerVo.getUsername());
            if (user == null) {
                result.rejectValue("username", null, "用户账号无效");
            }
        }

        if (result.hasErrors()) {
            model.addAttribute("mobileMode", mobileMode);
            model.addAttribute("user", registerVo);
            return "user/forgot";
        }

        if (mobileMode) {
            if (StringUtils.isEmpty(registerVo.getMobile())) {
                result.rejectValue("mobile", null, "手机号码不能为空");
            } else {
                if (!RegisterValidateHelper.validateMobile(registerVo.getMobile())) {
                    result.rejectValue("mobile", null, "手机号码无效");
                }
                if (!registerVo.getMobile().equals(user.getMobile())) {
                    result.rejectValue("username", null, "用户账号或手机号码错误");
                    result.rejectValue("mobile", null, "用户账号或手机号码错误");
                }
            }
        } else {
            if (StringUtils.isEmpty(registerVo.getEmail())) {
                result.rejectValue("email", null, "邮箱地址不能为空。");
            } else {
                if (!RegisterValidateHelper.validateEmail(registerVo.getEmail())) {
                    result.rejectValue("email", null, "邮箱地址无效");
                }
                if (!registerVo.getEmail().equals(user.getEmail())) {
                    result.rejectValue("username", null, "用户账号或邮箱地址错误");
                    result.rejectValue("email", null, "用户账号或邮箱地址错误");
                }
            }
        }

        if (result.hasErrors()) {
            model.addAttribute("mobileMode", mobileMode);
            model.addAttribute("user", registerVo);
            return "user/forgot";
        }

        try {
            //产生新的随机密码，并保存到用户记录中。
            String code = getNewPasswword();

            String clientId = getClientId(request);
            boolean sendResult = false;
            String sendError = "";
            if (mobileMode) {
                try {
                    String content = getContent(true, user.getUsername(), user.getMobile(), code);
                    HttpResult<String> smResult = smHistoryService.sendSm(clientId, user.getMobile(),
                            content, FuncPointType.RESET_PASSWORD, true, ReturnMode.SYNC_MODE);

                    if (smResult != null) {
                        //更新用户密码。
                        if (smResult.isSuccess()) {
                            userService.resetPassword(user.getId(), code);
                        } else {
                            throw new Exception(smResult.getMessage());
                        }

                        sendResult = smResult.isSuccess();
                        sendError = smResult.getMessage();
                    }
                } catch (Exception ex) {
                    sendResult = false;
                    sendError = ex.getMessage();
                }
            } else {
                try {
                    String content = getContent(false, user.getUsername(), user.getEmail(), code);
                    //发送验证邮件
                    emailSender.sendHtmlEmail(user.getEmail(), "TMT密码找回邮件", content);
                    sendResult = true;
                } catch (Exception ex) {
                    sendResult = false;
                    sendError = ex.getMessage();
                }
            }

            attr.addFlashAttribute("mobileMode", mobileMode);
            attr.addFlashAttribute("sendResult", sendResult);
            attr.addFlashAttribute("sendError", sendError);
            attr.addFlashAttribute("clientId", clientId);

            return "redirect:/forgot/result";

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        model.addAttribute("mobileMode", mobileMode);
        model.addAttribute("user", registerVo);
        return "user/forgot";
    }

    @RequestMapping(value = "/forgot/result", method = RequestMethod.GET)
    public String forgotResult(Model model, HttpServletRequest request,
                               @ModelAttribute("mobileMode") boolean mobileMode,
                               @ModelAttribute("sendResult") String sendResult,
                               @ModelAttribute("sendError") String sendError,
                               @ModelAttribute("clientId") String clientId) {
        model.addAttribute("mobileMode", mobileMode);
        model.addAttribute("sendResult", sendResult);
        model.addAttribute("sendError", sendError);
        model.addAttribute("clientId", clientId);
        return "user/forgot_result";
    }

    private String getContent(boolean mobileMode, String username, String address, String password) {
        String content = null;
        String msg = mobileMode ? systemParamService.getSystemParamValue(SystemParamCode.RETRIEVE_PASSWORD_MESSAGE_BY_MOBILE, String.class)
                : systemParamService.getSystemParamValue(SystemParamCode.RETRIEVE_PASSWORD_MESSAGE_BY_EMAIL, String.class);
        if (StringUtils.isEmpty(msg) || !msg.contains("{0}")) {
            msg = SystemParamCode.RETRIEVE_PASSWORD_MESSAGE_BY_EMAIL.getParamValue();
            content = MessageFormat.format(msg, password);
        } else {
            if (msg.contains("{1}") && msg.contains("2")) {
                content = MessageFormat.format(msg, password, username, address);
            } else if (msg.contains("{1}")) {
                content = MessageFormat.format(msg, username);
            } else if (msg.contains("{2}")) {
                content = MessageFormat.format(msg, address);
            } else {
                content = MessageFormat.format(msg, password);
            }
        }
        return content;
    }

    private String getNewPasswword() {
        String code1 = RandomCodeHelper.getLetterCode(2);
        code1 = code1.substring(0, 1).toUpperCase() + code1.substring(1).toLowerCase();
        String code2 = RandomCodeHelper.getNumberCode(4);
        return code1 + code2;
    }

    private boolean isMobileMode() {
        boolean mobileMode = false;
        try {
            String param = systemParamService.getSystemParamValue(SystemParamCode.RETRIEVE_PASSWORD_MODE, String.class);
            String[] subParams = param.split("\\|");
            mobileMode = "mobile".equals(subParams[0].trim().toLowerCase());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return mobileMode;
    }
}
